<!-- eslint-disable no-unused-vars -->
<script setup>
import { onMounted } from 'vue'
import * as d3 from 'd3'
import { forceData } from '../assets/js/data'
import {debounce} from '@/assets/js/utils'

onMounted(() => {
  init() // d3初始化
})

// d3初始化
function init() {

  // d3元素
  let rootEl = d3.select('#svg')

  // 保存宽度
  let width = rootEl.node().getBoundingClientRect().width
  // 保存高度
  let height = rootEl.node().getBoundingClientRect().height

  // 获取画布
  const svg = d3.select('#svg').append('svg').attr('width',width).attr('height',height)
  svg.style('background-color','#333')

  // 添加组
  const g = svg.append('g')

  // 获取原始数据
  const { forceNodes, forceLinks } = forceData
  console.log('获取原始数据:')
  console.log(forceNodes, 'forceNodes')
  console.log(forceLinks, 'forceLinks')
  const nodes = JSON.parse(JSON.stringify(forceNodes))
  const edges = JSON.parse(JSON.stringify(forceLinks))

  //设置一个color的颜色比例尺，为了让不同的扇形呈现不同的颜色
  const colorScale = d3.scaleOrdinal().domain(d3.range(nodes.length)).range(d3.schemeCategory10)

  // 新建力引导图
  const forceSimulation = d3
    .forceSimulation()
    .force('link', d3.forceLink())
    .force('charge', d3.forceManyBody().strength(-50))
    .force('center', d3.forceCenter())

  // 初始化力导向图,生成节点数据
  forceSimulation.nodes(nodes).on('tick', ticked) //这个函数很重要，后面给出具体实现和说明

  // 生成边数据
  forceSimulation
    .force('link')
    .id((d)=>d.id)
    .links(edges)
    .distance(function (d) {
      //每一边的长度
      return d.value * 100
    })

  // 设置图形的中心位置
  forceSimulation
    .force('center')
    .x(width / 2)
    .y(height / 2)

  // 在浏览器的控制台输出
  console.log('获取处理后数据:')
  console.log(nodes, 'nodes')
  console.log(edges, 'edges')

  //有了节点和边的数据后，绘制边
  const links = g
    .append('g')
    .selectAll('line')
    .data(edges)
    .enter()
    .append('line')
    .attr('stroke', function (d, i) {
      return colorScale(i)
    })
    .attr('stroke-width', 1)

  const linksText = g
    .append('g')
    .selectAll('text')
    .data(edges)
    .enter()
    .append('text')
    .attr('fill','#fff')
    .text(function (d) {
      return d.relation
    })

  //绘制节点，先为节点和节点上的文字分组
  const gs = g
    .selectAll('.circleText')
    .data(nodes)
    .enter()
    .append('g')
    .attr('transform', function (d, i) {
      const cirX = d.x
      const cirY = d.y
      return 'translate(' + cirX + ',' + cirY + ')'
    })
    .call(d3.drag().on('start', started).on('drag', dragged).on('end', ended))

  //绘制节点
  gs.append('circle')
    .attr('r', 50)
    .attr('fill-opacity',0.5)
    .attr('stroke','#fff')
    .attr('stroke-width','1')
    .attr('fill', function (d, i) {
      return colorScale(i)
    })

  //文字
  gs.append('text')
    .attr('x', 0)
    .attr('y', -6)
    .attr('dy', 10)
    .attr('text-anchor', 'middle')
    .attr('fill','#fff')
    .text(function (d) {
      return d.name
    })


  function ticked() {
    links
      .attr('x1', function (d) {
        return d.source.x
      })
      .attr('y1', function (d) {
        return d.source.y
      })
      .attr('x2', function (d) {
        return d.target.x
      })
      .attr('y2', function (d) {
        return d.target.y
      })
    linksText
      .attr('x', function (d) {
        return (d.source.x + d.target.x) / 2
      })
      .attr('y', function (d) {
        return (d.source.y + d.target.y) / 2
      })
    gs.attr('transform', function (d) {
      return 'translate(' + d.x + ',' + d.y + ')'
    })
  }

  // 开始拖动
  function started(d) {
    if (!d.active) {
      forceSimulation.alphaTarget(0.8).restart()
    }
    d.subject.fx = d.subject.x
    d.subject.fy = d.subject.y
  }

  // 拖动中
  function dragged(d) {
    d.subject.fx = d.x
    d.subject.fy = d.y
  }

  // 结束拖动
  function ended(d) {
    if (!d.active) {
      forceSimulation.alphaTarget(0)
    }
    d.subject.fx = null
    d.subject.fy = null
  }

  // 检测屏幕尺寸变化更改尺寸
  d3.select(window).on('resize', debounce(init,500))
}
</script>

<template>
  <div class="d_svg_paper" id="svg"></div>
</template>

<style>
.d_svg_paper{
  height: 100vh;
  width: 100%;
  overflow: hidden;
}
</style>
